package com.hc.server.actions;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.hc.server.Config;
import com.hc.server.Error;
import com.hc.server.IAction;
import com.hc.server.Request;
import com.hc.server.Response;
import com.hc.server.conn.bill.BillResponse;
import com.hc.server.conn.bill.BillServerHelper;
import com.hc.server.conn.mall.MallResponse;
import com.hc.server.conn.mall.MallServerHelper;
import com.hc.server.db.DBFactory;
import com.hc.server.db.Mporder;
import com.hc.server.db.Ordermap;
import com.hc.server.util.Util;

/**
 * 预定商品
 * @author xujh
 *
 */
public class BOOK_GOODS implements IAction{

	private static final String USER_ID = "USER_ID";
	private static final String PHONE = "PHONE";
	private static final String GOODSLIST = "GOODSLIST";
	private static final String CONTACT = "CONTACT";//联系方式
	private static final String PAYABLES = "PAYABLES";//应付款
	private static final String BILL = "BILL";
	
	private static final String MALL_ORDERSN = "orderSn";
//	private static final String MALL_PDTSN = "pdtSn";
	private static final String MALL_PDTNAME = "pdtName";
//	private static final String MALL_PDTTYPE = "pdtType";
//	private static final String MALL_CHECKIN = "sdate";
//	private static final String MALL_CHECKOUT = "edate";
//	private static final String MALL_PRICE = "price";
	private static final String MALL_COUNT = "count";
	private static final String MALL_AMOUNT = "amount";
//	private static final String MALL_CREATETIME = "createDate";
	private static final String MALL_REMARK = "remark";

	@Override
	public void execute(Request req, Response resp) {
		//获取参数
		String userId;
		String phone;
		JSONArray goodsList;//商品列表
		JSONObject contact; //联系方式
		int payables;		//预定时的应付金额
		try {
			userId = req.getStrArg(USER_ID);
			phone = req.getStrArg(PHONE);
			goodsList = req.getJSONArrayArg(GOODSLIST);
			contact = req.getJSONObjectArg(CONTACT);
			payables = req.getIntArg(PAYABLES);
		} catch (JSONException e) {
			resp.setErrResp(Error.INVALID_ARGS_ERR_CD, Error.INVALID_ARGS_ERR_MSG);
			return;
		}
		//到商城预定
		int amount = 0;//金额根据商城预定成功结果进行累计。
		JSONArray des = new JSONArray();//描述
		JSONArray remarks = new JSONArray();//备注
		ArrayList<String> mallOrdreSnArray = new ArrayList<String>();//商城订单编号
		//如果多个商品一起预订过程中出现了异常，会导致已经在商场预订的商品被锁定。
		for(int i=0; i<goodsList.length(); i++){
			JSONObject goods;
			try {
				goods = goodsList.getJSONObject(i);
			} catch (JSONException e) {
				cancelOtherOrder(mallOrdreSnArray);
				resp.setErrResp(Error.INVALID_ARGS_ERR_CD, Error.INVALID_ARGS_ERR_MSG);
				return;
			}
			MallResponse mallResp;
			try {
				mallResp = MallServerHelper.bookGoods(goods, contact);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
				cancelOtherOrder(mallOrdreSnArray);
				resp.setErrResp(Error.INVALID_ARGS_ERR_CD, Error.INVALID_ARGS_ERR_MSG);
				return;
			} catch (IOException e) {
				e.printStackTrace();
				//TODO 报警
				cancelOtherOrder(mallOrdreSnArray);
				resp.setErrResp(Error.MALLSERVER_NET_ERR_CD, Error.MALLSERVER_NET_ERR_MSG);
				return;
			} catch (JSONException e) {
				e.printStackTrace();
				cancelOtherOrder(mallOrdreSnArray);
				resp.setErrResp(Error.MALLSERVER_DATA_FORMAT_ERR_CD, Error.MALLSERVER_DATA_FORMAT_ERR_MSG);
				return;
			}
			if(0 == mallResp.getRetCode()){
				JSONObject mallOrder = mallResp.getResult();
				try{
					String sn = mallOrder.getString(MALL_ORDERSN);
					mallOrdreSnArray.add(sn);
					amount += mallOrder.getInt(MALL_AMOUNT);
					int count = mallOrder.getInt(MALL_COUNT);
					String pdtName = mallOrder.getString(MALL_PDTNAME);
					String remark = mallOrder.getString(MALL_REMARK);
					des.put(pdtName);
					des.put("数量： "+count);
					switch (goods.getInt("TYPE")) {
						case Config.TYPE_HOTEL:
							des.put("日期： "+goods.getString("CHECKIN_DATE")+" 到 "+goods.getString("CHECKOUT_DATE"));
							break;
						case Config.TYPE_ACT:
						case Config.TYPE_TICKET:
						case Config.TYPE_TRAVEL:
						case Config.TYPE_AIR://FIXME:机票不对
							des.put("使用日期： "+goods.getString("CHECKIN_DATE"));
							break;
						case Config.TYPE_SPECIAL:
							break;
						default:
							break;
					}
					des.put(remark);
				}catch (JSONException e) {
					cancelOtherOrder(mallOrdreSnArray);
					e.printStackTrace();
					resp.setErrResp(Error.MALLSERVER_DATA_FORMAT_ERR_CD, Error.MALLSERVER_DATA_FORMAT_ERR_MSG);
					return;
				}
			}else if(1003 == mallResp.getRetCode()){
				String name = goods.optString("PDT_NAME");
				remarks.put(name+"库存不足；");
			}
		}
		//添加联系人信息
		des.put("联系人： "+contact.optString("NAME"));
		int idType = contact.optInt("ID_TYPE");
		switch (idType) {
		case Config.IDTYPE_SFZ:
			des.put("身份证: "+contact.optString("ID_NUM"));
			break;
		case Config.IDTYPE_HZ:
			des.put("护照： "+contact.optString("ID_NUM"));
			break;
		case Config.IDTYPE_JGZ:
			des.put("军官证: "+contact.optString("ID_NUM"));
			break;
		default:
			break;
		}
		String address = contact.optString("ADD");
		if(!address.isEmpty()){
			des.put("联系地址： "+address);
		}
		String lphone = contact.optString("PHONE");
		if(!lphone.isEmpty()){
			des.put("联系电话： "+lphone);
		}
		//如果商城订单不存在则表明库存不足
		if(mallOrdreSnArray.isEmpty()){
			resp.setErrResp(Error.STOCK_NOT_ENOUGH_CD, Error.STOCK_NOT_ENOUGH_MSG );
			return;
		}
		if(amount != payables ){
			remarks.put("注意付款金额可能因为临时价格调整或商品调整与预定不符！请确认清楚再支付！");
		}
		//创建订单
		Mporder order = new Mporder();
		Session session = DBFactory.openSession();
		Transaction t = session.beginTransaction();
		try{
			t.begin();
			order.setAmount(amount);
			Date createTime = new Date();
			order.setCreateTime(createTime);
			order.setDes(des.toString());
			Date invalidTime = new Date(createTime.getTime()+Config.ORDER_INVALID_TIME);//失效时间为5分钟。
			order.setInvalidTime(invalidTime);
			order.setPhone(phone);
			order.setUser(userId);
			order.setRemark(remarks.toString());
			order.setStatus(Config.ORDER_NEW);
			session.saveOrUpdate(order);
			for(int i=0; i<mallOrdreSnArray.size(); i++){
				Ordermap map = new Ordermap();
				map.setMallorderId(mallOrdreSnArray.get(i));
				map.setMporder(order);
				session.saveOrUpdate(map);
			}
			order.getOrdermaps();
			t.commit();
		}catch (Exception e) {
			e.printStackTrace();
			t.rollback();
			resp.setErrResp(Error.SERVER_SYS_ERR_CD, Error.SERVER_SYS_ERR_MSG);
			return;
		}finally{
			session.close();
		}
		String orderId = order.getId().toString();
		
		//创建账单
		BillResponse bsResp = null;
		try {
			bsResp = BillServerHelper.createBill(orderId, phone, amount, des.toString());
		} catch (IOException e) {
			cancelMallOrder(order);
			e.printStackTrace();
			resp.setErrResp(Error.BILLSERVER_NET_ERR_CD, Error.BILLSERVER_NET_ERR_MSG);
			return;
		} catch (JSONException e) {
			cancelMallOrder(order);
			e.printStackTrace();
			resp.setErrResp(Error.BILLSERVER_DATA_FORMAT_ERR_CD, Error.BILLSERVER_DATA_FORMAT_ERR_MSG);
			return;
		}
		if(0 != bsResp.getRetCode()){
			cancelMallOrder(order);
			resp.setErrResp(Error.BILLSERVER_ERR_CD, Error.BILLSERVER_ERR_MSG);
			return;
		}else{
			//修改订单状态为待支付
			modify2Paying(order);
		}
		//返回订单
		resp.appendRespContent("ORDER", Order2JSON(order));
		resp.appendRespContent(BILL, bsResp.getResult());
	}

	private JSONObject Order2JSON(Mporder order) {
		JSONObject jOrder = new JSONObject();
		try{
			jOrder.put("OID", order.getId());
			jOrder.put("AMOUNT", order.getAmount());
			jOrder.put("CREAT_TIME", Util.Date2Time(order.getCreateTime()));
			jOrder.put("DES", order.getDes());
			jOrder.put("REMARK", order.getRemark());
			jOrder.put("STATUS", order.getStatus());
		}catch (JSONException e) {
			e.printStackTrace();
		}
		return jOrder;
	}

	private void cancelOtherOrder(ArrayList<String> mallOrdreSnArray) {
		for(int i=0; i < mallOrdreSnArray.size(); i++){
			String orderId = mallOrdreSnArray.get(i);
			MallResponse resp;
			try {
				resp = MallServerHelper.cancelOrder(orderId);
				if(0 != resp.getRetCode()){
					//TODO 如果取消失败怎么办，报警
				}
			} catch (Exception e) {
				e.printStackTrace();
				//TODO 报警
			} 
		}
	}

	private void modify2Paying(Mporder order) {
		Session session;
		Transaction t;
		session = DBFactory.openSession();
		t = session.beginTransaction();
		try{
			t.begin();
			order = (Mporder) session.load(Mporder.class, order.getId());
			if(Config.ORDER_NEW == order.getStatus()){
				order.setStatus(Config.ORDER_PAYING);//修改订单为待支付
				session.saveOrUpdate(order);
			}
			t.commit();
		}catch (Exception e) {
			e.printStackTrace();
			t.rollback();
		}finally{
			session.close();
		}
	}

	private void cancelMallOrder(Mporder order) {
		Session session;
		Transaction t;
		session = DBFactory.openSession();
		t = session.beginTransaction();
		try{
			t.begin();
			//取消订单,为什么要重新load才行
			order = (Mporder) session.load(Mporder.class, order.getId());
			Set<Ordermap> maps = order.getOrdermaps();
			Iterator<Ordermap> mapIter = maps.iterator();
			while(mapIter.hasNext()){
				Ordermap map = mapIter.next();
				String mallOrderId = map.getMallorderId();
				try{
					MallResponse resp = MallServerHelper.cancelOrder(mallOrderId);
					if(0 != resp.getRetCode()){
						//TODO：报警
					}
				}catch (Exception e) {
					e.printStackTrace();
					//TODO 报警
				}
			}
			//修改订单为失效
			order.setStatus(Config.ORDER_INVALID);
			session.saveOrUpdate(order);
			t.commit();
		}catch (Exception e) {
			e.printStackTrace();
			t.rollback();
		}finally{
			session.close();
		}
	}

}
